pub mod filter;
// pub mod git;
pub mod path;
pub mod template;
pub mod token;

use std::path::Path;
use serde_json::json;

pub use filter::should_include_file;
// pub use git::{get_git_diff, get_git_diff_between_branches, get_git_log};
pub use path::{label, traverse_directory};
pub use template::{
    copy_to_clipboard, handle_undefined_variables, handlebars_setup, render_template, write_to_file,
};
pub use token::{count_tokens, get_model_info, get_tokenizer};

const DEFAULT_TEMPLATE_NAME: &str = "default";
const _CUSTOM_TEMPLATE_NAME: &str = "custom";

const DEFAULT_TEMPLATE_CONTENT: &str = r#"
Project Path: {{ absolute_code_path }}

Source Tree:

```
{{ source_tree }}
```

{{#each files}}
{{#if code}}
`{{path}}`:

{{code}}

{{/if}}
{{/each}}
"#;


pub fn codes2prompts(path: &str) -> Result<String, anyhow::Error> {

    let include_patterns = vec![];
    let exclude_patterns = vec![];

    let path = Path::new(path);

    // Traverse the directory
    let create_tree = traverse_directory(
        path,
        &include_patterns,
        &exclude_patterns,
        false,
        false,
        true,
        false,
        false,
    );

    let (template_content, template_name) = (DEFAULT_TEMPLATE_CONTENT, DEFAULT_TEMPLATE_NAME);
    let handlebars = handlebars_setup(template_content, template_name).expect("Failed to setup handlebars");

    let (tree, files) = match create_tree {
        Ok(result) => result,
        Err(e) => {
            anyhow::bail!("Failed to build directory tree: {}", e);
        }
    };

    // Prepare JSON Data
    let mut data = json!({
        "absolute_code_path": label(path),
        "source_tree": tree,
        "files": files,
        "git_diff": Option::<String>::None,
        "git_diff_branch": Option::<String>::None,
        "git_log_branch": Option::<String>::None
    });
    
    // Handle undefined variables
    handle_undefined_variables(&mut data, &template_content)?;
    
    // Render the template
    let rendered = render_template(&handlebars, template_name, &data)?;

    Ok(rendered)

}
